/* eslint-disable no-undef */
import React, { useEffect, useState, useContext } from "react";
// import {
//   GithubLogo,
//   GitMerge,
//   EnvelopeSimple,
//   Plus,
// } from "@phosphor-icons/react";
import NewWorkspaceModal, {
  useNewWorkspaceModal,
} from "../Modals/NewWorkspace";
// import paths from "@/utils/paths";
import { isMobile } from "react-device-detect";
import { SidebarMobileHeader } from "../Sidebar";
import ChatBubble from "../ChatBubble";
import System from "@/models/system";
import UserIcon from "../UserIcon";
import { userFromStorage } from "@/utils/request";
import useUser from "@/hooks/useUser";
import { useTranslation, Trans } from "react-i18next";
import Appearance from "@/models/appearance";
import { useChatMessageAlignment } from "@/hooks/useChatMessageAlignment";
import PromptInput, {
  PROMPT_INPUT_EVENT,
} from "../WorkspaceChat/ChatContainer/PromptInput";
import DnDFileUploaderWrapper, {
  DndUploaderContext,
} from "../WorkspaceChat/ChatContainer/DnDWrapper";
import SpeechRecognition, {
  useSpeechRecognition,
} from "react-speech-recognition";
import LocalDeploy from "../WorkspaceChat/ChatContainer/LocalDeploy";
import "./index.css";
export default function DefaultChatContainer() {
  const { getMessageAlignment } = useChatMessageAlignment();
  const { showScrollbar } = Appearance.getSettings();
  const [mockMsgs, setMockMessages] = useState([]);
  const { user } = useUser();
  const [fetchedMessages, setFetchedMessages] = useState([]);
  const [message, setMessage] = useState("");
  const [chatHistory, setChatHistory] = useState([]);
  const { files, parseAttachments } = useContext(DndUploaderContext);
  const [loadingResponse, setLoadingResponse] = useState(false);
  const {
    showing: showingNewWsModal,
    showModal: showNewWsModal,
    hideModal: hideNewWsModal,
  } = useNewWorkspaceModal();
  const popMsg = !window.localStorage.getItem("anythingllm_intro");
  const { t } = useTranslation();
  const { listening, resetTranscript } = useSpeechRecognition({
      clearTranscriptOnListen: true,
    });
  useEffect(() => {
    const fetchData = async () => {
      const fetchedMessages = await System.getWelcomeMessages();
      setFetchedMessages(fetchedMessages);
    };
    fetchData();
  }, []);

  const MESSAGES = [
    <React.Fragment key="msg1">
      <MessageContainer>
        <MessageContent alignmentCls={getMessageAlignment("user")}>
          <MessageText role={"user"}>简单介绍一下产品</MessageText>
        </MessageContent>
      </MessageContainer>
    </React.Fragment>,

    <React.Fragment key="msg2">
      <MessageContainer>
        <MessageContent alignmentCls={getMessageAlignment("assistant")}>
          <UserIcon user={{ uid: "system" }} role={"assistant"} />
          <MessageText role={"assistant"}>
            欢迎使用字狐AnythingLLM，可以将任何东西转换为你可以查询和聊天的训练有素的聊天机器人。
            字狐AnythingLLM 是将强大的 AI 产品（如
            OpenAi、GPT-4、LangChain、PineconeDB、ChromaDB
            等）整合在一个整洁的包中而无需繁琐操作的最简单方法，可以将你的生产力提高
            100 倍。 字狐AnythingLLM
            可以完全在你的本地计算机上运行，几乎没有开销，你甚至不会注意到它的存在！无需GPU，也可以进行云端和本地安装。
            AI工具生态系统每天都在变得更强大，字狐AnythingLLM 使其易于使用。
          </MessageText>
        </MessageContent>
      </MessageContainer>
    </React.Fragment>,

    <React.Fragment key="msg3">
      <MessageContainer>
        <MessageContent alignmentCls={getMessageAlignment("user")}>
          <MessageText role={"user"}>我该怎么使用？</MessageText>
        </MessageContent>
      </MessageContainer>
    </React.Fragment>,

    <React.Fragment key="msg4">
      <MessageContainer>
        <MessageContent alignmentCls={getMessageAlignment("assistant")}>
          <UserIcon
            user={{ uid: userFromStorage()?.username }}
            role={"assistant"}
          />
          <MessageText role={"assistant"}>
            很简单。所有集合都组织成我们称之为“工作区”的桶。工作区是文件、文档、图像、PDF
            和其他文件的存储桶，这些文件将被转换为LLM可以理解和在对话中使用的内容，你可以随时添加和删除文件。
            字狐AnythingLLM 提供了两种与你的数据交流的方式：
            查询：你的聊天将返回在你的工作区中访问的文档中找到的数据或推论。向工作区添加更多文档会使其更智能！
            对话：你的文档和正在进行的聊天记录同时为 LLM
            知识做出贡献。非常适合添加基于文本的实时信息或纠正 LLM
            可能存在的误解。你可以在聊天过程中切换模式！现在立即本地部署模型吧！
          </MessageText>
        </MessageContent>
      </MessageContainer>
    </React.Fragment>,
  ];

  useEffect(() => {
    function processMsgs() {
      if (!!window.localStorage.getItem("anythingllm_intro")) {
        setMockMessages([...MESSAGES]);
        return false;
      } else {
        setMockMessages([MESSAGES[0]]);
      }

      var timer = 500;
      var messages = [];

      MESSAGES.map((child) => {
        setTimeout(() => {
          setMockMessages([...messages, child]);
          messages.push(child);
        }, timer);
        timer += 2_500;
      });
      window.localStorage.setItem("anythingllm_intro", 1);
    }
    processMsgs();
  }, []);

  const handleMessageChange = (event) => {
    setMessage(event.target.value);
  };

  const setMessageEmit = (messageContent = "") => {
    setMessage(messageContent);
    window.dispatchEvent(
      new CustomEvent(PROMPT_INPUT_EVENT, { detail: messageContent })
    );
  };

  const handleSubmit = async (event) => {
    event.preventDefault();
    if (!message || message === "") return false;
    const prevChatHistory = [
      ...chatHistory,
      {
        content: message,
        role: "user",
        attachments: parseAttachments(),
      },
      {
        content: "",
        role: "assistant",
        pending: true,
        userMessage: message,
        animate: true,
      },
    ];

    if (listening) {
      // Stop the mic if the send button is clicked
      endSTTSession();
    }
    setChatHistory(prevChatHistory);
    setMessageEmit("");
    setLoadingResponse(true);
  };

  function endSTTSession() {
    SpeechRecognition.stopListening();
    resetTranscript();
  }

  const sendCommand = async (
    command,
    submit = false,
    history = [],
    attachments = []
  ) => {
    if (!command || command === "") return false;
    if (!submit) {
      setMessageEmit(command);
      return;
    }

    let prevChatHistory;
    if (history.length > 0) {
      // use pre-determined history chain.
      prevChatHistory = [
        ...history,
        {
          content: "",
          role: "assistant",
          pending: true,
          userMessage: command,
          attachments,
          animate: true,
        },
      ];
    } else {
      prevChatHistory = [
        ...chatHistory,
        {
          content: command,
          role: "user",
          attachments,
        },
        {
          content: "",
          role: "assistant",
          pending: true,
          userMessage: command,
          animate: true,
        },
      ];
    }
    setChatHistory(prevChatHistory);
    setMessageEmit("");
    setLoadingResponse(true);
  };

  return (
    <>
      <div
        className={`transition-all duration-500 relative w-full overflow-y-scroll h-[calc(100%-36px-180px-38px)] ${
          showScrollbar ? "show-scrollbar" : "no-scroll"
        }`}
      >
        {isMobile && <SidebarMobileHeader />}
        {fetchedMessages?.length === 0
          ? mockMsgs.map((content, i) => {
              return <React.Fragment key={i}>{content}</React.Fragment>;
            })
          : fetchedMessages?.map((fetchedMessage, i) => {
              return (
                <React.Fragment key={i}>
                  <ChatBubble
                    message={
                      fetchedMessage.user === ""
                        ? fetchedMessage.response
                        : fetchedMessage.user
                    }
                    type={fetchedMessage.user === "" ? "response" : "user"}
                    popMsg={popMsg}
                  />
                </React.Fragment>
              );
            })}
        {showingNewWsModal && <NewWorkspaceModal hideModal={hideNewWsModal} />}
      </div>
      <LocalDeploy />
      <PromptInput
        submit={handleSubmit}
        onChange={handleMessageChange}
        isStreaming={loadingResponse}
        sendCommand={sendCommand}
        attachments={files}
      />
    </>
  );
}
function MessageContainer({ children }) {
  return (
    <div className="flex justify-center items-end w-full mb-[32px]">
      <div className="w-full flex md:max-w-[1200px] flex-col">{children}</div>
    </div>
  );
}

function MessageContent({ children, alignmentCls = "" }) {
  return (
    <div className={`flex gap-x-2 justify-end ${alignmentCls}`}>{children}</div>
  );
}

function MessageText({ children, role }) {
  return (
    <span
      style={{ lineHeight: "26px" }}
      className={`light:text-theme-text-primary text-[15px] pt-[13px] text-theme-text-primary max-w-[calc(100%-48px-10px)] chat-${role}-text`}
    >
      {children}
    </span>
  );
}
